package monopoly.frames;

import java.awt.AlphaComposite;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RadialGradientPaint;
import java.awt.RenderingHints;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

import javax.swing.JComponent;
import javax.swing.JLayer;
import javax.swing.JPanel;
import javax.swing.plaf.LayerUI;

@SuppressWarnings("serial")
public class FrameReloj extends TransparentJInternalFrame {
    private final Calendar cal = Calendar.getInstance();
    private final Date horaActual = new Date();
    private final SimpleDateFormat formatoHora = new SimpleDateFormat("dd/MMM/yyyy - h:mm:ss a");
    private final double piMedios = Math.PI / 2;
    private double escala, segundos, minutos, hora;
    private int centroX, centroY;        

    public FrameReloj() {
        setTitle(formatoHora.format(horaActual).toUpperCase());
        setResizable(true);
        //setFrameIcon(imageIcon);
        setSize(300, 300);
        setMinimumSize(new Dimension(100, 100));
        setLocation(10, 10);
        setTransparentColor(new Color(225, 192, 0, 69));
        getRootPane().setOpaque(false);
        setContentPane(new JLayer<>(new JPanel() {
            private final Color anaranjado     = new Color(220, 128, 0);
            private final Color azulOscuro     = new Color(28, 28, 65);
            private BasicStroke strokeSegundos = new BasicStroke(1.3F, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
            private BasicStroke strokeMinutos  = new BasicStroke(2.5F, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
            private BasicStroke strokeHoras    = new BasicStroke(5.5F, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
            private BasicStroke strokeCirculo  = new BasicStroke(3.5F, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
            private int w, h;
            private BufferedImage bi;
            private Graphics2D gbi;
    
            public void paint(Graphics g) {
                if (w != getWidth() || h != getHeight()) {
                    w = getWidth();
                    h = getHeight();
                    centroX = w / 2;
                    centroY = h / 2;
                    bi  = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
                    gbi = bi.createGraphics();
                    escala = (double)Math.min(w, h) / 200.0D;
                    gbi.setFont(new Font("Snap ITC", Font.PLAIN, (int)(11 * escala)));
                    strokeSegundos = new BasicStroke(1.3F * (float) escala, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
                    strokeMinutos  = new BasicStroke(2.5F * (float) escala, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
                    strokeHoras    = new BasicStroke(5.5F * (float) escala, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
                    strokeCirculo  = new BasicStroke(3.5F * (float) escala, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
                    if(w < 180) {
                        applyPattern("h:mm:ss a");
                    } else if(w < 200) {
                        applyPattern("dd/MM/yy - h:mm:ss a");
                    } else if(w < 225) {
                        applyPattern("dd/MM/yyyy - h:mm:ss a");
                    } else if(w < 300) {
                        applyPattern("dd/MMM/yyyy - h:mm:ss a");
                    } else if(w < 375) {
                        applyPattern("dd/MMMM/yyyy - h:mm:ss a");
                    } else if(w < 400) {
                        applyPattern("d 'de' MMMM 'de' yyyy - h:mm:ss a");
                    } else if(w < 450) {
                        applyPattern("E, d 'de' MMMM 'de' yyyy - h:mm:ss a");
                    } else if(w < 550) {
                        applyPattern("EEEE, d 'de' MMMM 'de' yyyy - h:mm:ss a");
                    } else {
                        applyPattern("EEEE, d 'de' MMMM 'de' yyyy - h:mm:ss a, zzzz");
                    }
                }
                gbi.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                gbi.setColor(Color.LIGHT_GRAY);
                gbi.fillOval((int)(centroX - 80 * escala), (int)(centroY - 80 * escala), (int)(160 * escala), (int)(160 * escala));
                gbi.setStroke(strokeCirculo);
                gbi.setColor(azulOscuro);
                gbi.drawOval((int)(centroX - 80 * escala), (int)(centroY - 80 * escala), (int)(160 * escala), (int)(160 * escala));
                double doubleAux;
                for (int i = 1; i < 12; i++) {
                    doubleAux = Math.toRadians(30 * i) - piMedios;
                    gbi.drawString(String.valueOf(i), (int) (centroX + 70 * escala * Math.cos(doubleAux) - 4 * escala), (int) (centroY + 70 * escala * Math.sin(doubleAux)) + (int)(4 * escala));
                }
                gbi.drawString("12", (int) (centroX + 70 * escala * Math.cos(Math.toRadians(30 * 12) - piMedios) - 6 * escala), (int) (centroY + 70 * escala * Math.sin(Math.toRadians(30 * 12) - piMedios)) + (int)(4 * escala));
                gbi.setColor(anaranjado);
                gbi.setStroke(strokeHoras);
                doubleAux = Math.toRadians(30.0D * hora) - piMedios;
                gbi.drawLine(centroX, centroY, centroX + (int)(50.0D * escala * Math.cos(doubleAux)), centroY + (int)(50.0D * escala * Math.sin(doubleAux)));
                gbi.setStroke(strokeMinutos);
                doubleAux = Math.toRadians(6.0D  * minutos) - piMedios;
                gbi.drawLine(centroX, centroY, centroX + (int)(60.0D * escala * Math.cos(doubleAux)), centroY + (int)(60.0D * escala * Math.sin(doubleAux)));
                gbi.setStroke(strokeSegundos);
                doubleAux = Math.toRadians(6.0D * segundos) - piMedios;
                gbi.drawLine(centroX, centroY, centroX + (int)(70.0D * escala * Math.cos(doubleAux)), centroY + (int)(70.0D * escala * Math.sin(doubleAux)));
                gbi.setColor(azulOscuro);
                gbi.fillOval(centroX - (int)(4 * escala), centroY - (int)(4 * escala), (int)(8 * escala), (int)(8 * escala));
                ((Graphics2D) g).drawImage(bi, 0, 0, this);
            }
            
            private void applyPattern(String pattern){
                if(!formatoHora.toPattern().equals(pattern)){
                    formatoHora.applyPattern(pattern);
                    setTitle(formatoHora.format(horaActual).toUpperCase());
                }
            }
        }, new LayerUI<JPanel>() {
            private final float radius = 85.0F;
            private final float[] dist = {0.0F, 0.08F, 1.0F};
            private final Color[] colors = {new Color(0, 0, 64, 200), new Color(0, 0, 255, 200), new Color(0, 0, 0, 0)};
            private final AlphaComposite alphaComposite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.6F);
            private final Point2D center = new Point2D.Double(centroX, centroY);

            public void paint(Graphics g, JComponent c) {
                final Graphics2D g2 = (Graphics2D) g.create();
                super.paint(g2, c);                    
                center.setLocation(centroX, centroY);
                g2.setPaint(new RadialGradientPaint(center, (int)(radius * escala), dist, colors));
                g2.setComposite(alphaComposite);
                g2.fillRect(0, 0, c.getWidth(), c.getHeight());
                g2.dispose();
            }
        }));
        final Thread hiloFrameReloj = new Thread(){
            public void run() {
                try {
                    for(;;) {
                        updateFrameReloj();
                        repaint();
                        sleep(1000L);
                    }
                } catch (InterruptedException ignorada) {
                }
            }
        };
        hiloFrameReloj.setPriority(Thread.MIN_PRIORITY);
        hiloFrameReloj.start();
        setVisible(true);
    }

    private void updateFrameReloj() {
        horaActual.setTime(System.currentTimeMillis());
        cal.setTime(horaActual);
        setTitle(formatoHora.format(horaActual).toUpperCase());
        segundos = (double) cal.get(Calendar.SECOND);
        minutos  = (double) cal.get(Calendar.MINUTE) + segundos / 60.0D;
        hora     = (double) cal.get(Calendar.HOUR) + minutos / 60.0D;
    }
}